home *** CD-ROM | disk | FTP | other *** search
- /* WaveTableObject.c */
- /*****************************************************************************/
- /* */
- /* Out Of Phase: Digital Music Synthesis on General Purpose Computers */
- /* Copyright (C) 1994 Thomas R. Lawrence */
- /* */
- /* This program is free software; you can redistribute it and/or modify */
- /* it under the terms of the GNU General Public License as published by */
- /* the Free Software Foundation; either version 2 of the License, or */
- /* (at your option) any later version. */
- /* */
- /* This program is distributed in the hope that it will be useful, */
- /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
- /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
- /* GNU General Public License for more details. */
- /* */
- /* You should have received a copy of the GNU General Public License */
- /* along with this program; if not, write to the Free Software */
- /* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
- /* */
- /* Thomas R. Lawrence can be reached at tomlaw@world.std.com. */
- /* */
- /*****************************************************************************/
-
- #include "MiscInfo.h"
- #include "Audit.h"
- #include "Debug.h"
- #include "Definitions.h"
-
- #include "WaveTableObject.h"
- #include "Array.h"
- #include "WaveTableList.h"
- #include "Memory.h"
- #include "DataMunging.h"
- #include "FixedPoint.h"
- #include "WaveTableWindow.h"
- #include "WaveTableStorage.h"
- #include "BufferedFileInput.h"
- #include "BufferedFileOutput.h"
- #include "BinaryCodedDecimal.h"
-
-
- struct WaveTableObjectRec
- {
- MyBoolean DataModified;
-
- char* Name;
- WaveTableStorageRec* WaveTableData;
- char* WaveTableFormula;
- double TestAttackDuration;
- double TestDecayDuration;
- double TestFrequency;
- long TestSamplingRate;
-
- WaveTableWindowRec* WaveTableWindow;
-
- struct CodeCenterRec* CodeCenter;
- struct MainWindowRec* MainWindow;
- WaveTableListRec* WaveTableList;
-
- short SavedWindowXLoc;
- short SavedWindowYLoc;
- short SavedWindowWidth;
- short SavedWindowHeight;
- };
-
-
- /* create a new wave table object with reasonable defaults. */
- WaveTableObjectRec* NewWaveTableObject(struct CodeCenterRec* CodeCenter,
- struct MainWindowRec* MainWindow,
- struct WaveTableListRec* WaveTableList)
- {
- WaveTableObjectRec* WaveTableObj;
-
- WaveTableObj = (WaveTableObjectRec*)AllocPtrCanFail(sizeof(WaveTableObjectRec),
- "WaveTableObjectRec");
- if (WaveTableObj == NIL)
- {
- FailurePoint1:
- return NIL;
- }
- WaveTableObj->DataModified = False;
- WaveTableObj->WaveTableWindow = NIL;
- WaveTableObj->CodeCenter = CodeCenter;
- WaveTableObj->MainWindow = MainWindow;
- WaveTableObj->WaveTableList = WaveTableList;
- WaveTableObj->TestAttackDuration = 1;
- WaveTableObj->TestDecayDuration = 2;
- WaveTableObj->TestFrequency = 261.625565300598635;
- WaveTableObj->TestSamplingRate = 22050;
- WaveTableObj->SavedWindowXLoc = 0;
- WaveTableObj->SavedWindowYLoc = 0;
- WaveTableObj->SavedWindowWidth = 0;
- WaveTableObj->SavedWindowHeight = 0;
- WaveTableObj->Name = StringToBlockCopy("untitled");
- if (WaveTableObj->Name == NIL)
- {
- FailurePoint2:
- ReleasePtr((char*)WaveTableObj);
- goto FailurePoint1;
- }
- WaveTableObj->WaveTableFormula = StringToBlockCopy(
- "# data : fixedarray; frames : integer; tables : integer\x0a");
- if (WaveTableObj->WaveTableFormula == NIL)
- {
- FailurePoint3:
- ReleasePtr(WaveTableObj->Name);
- goto FailurePoint2;
- }
- WaveTableObj->WaveTableData = NewWaveTableStorage(eSample16bit,256);
- if (WaveTableObj->WaveTableData == NIL)
- {
- FailurePoint4:
- ReleasePtr(WaveTableObj->WaveTableFormula);
- goto FailurePoint3;
- }
- return WaveTableObj;
- }
-
-
- /* create a new wave table based on the data being passed in. */
- WaveTableObjectRec* NewWaveTableObjectFromData(struct CodeCenterRec* CodeCenter,
- struct MainWindowRec* MainWindow,
- struct WaveTableListRec* WaveTableList, char* RawData,
- NumBitsType NumBits, long NumTables, long FramesPerTable)
- {
- long Scan;
- WaveTableObjectRec* WaveTableObj;
-
- WaveTableObj = (WaveTableObjectRec*)AllocPtrCanFail(sizeof(WaveTableObjectRec),
- "WaveTableObjectRec");
- if (WaveTableObj == NIL)
- {
- FailurePoint1:
- return NIL;
- }
- WaveTableObj->DataModified = False;
- WaveTableObj->WaveTableWindow = NIL;
- WaveTableObj->CodeCenter = CodeCenter;
- WaveTableObj->MainWindow = MainWindow;
- WaveTableObj->WaveTableList = WaveTableList;
- WaveTableObj->TestAttackDuration = 1;
- WaveTableObj->TestDecayDuration = 2;
- WaveTableObj->TestFrequency = 261.625565300598635;
- WaveTableObj->TestSamplingRate = 22050;
- WaveTableObj->SavedWindowXLoc = 0;
- WaveTableObj->SavedWindowYLoc = 0;
- WaveTableObj->SavedWindowWidth = 0;
- WaveTableObj->SavedWindowHeight = 0;
- WaveTableObj->Name = StringToBlockCopy("AlgoWaveTable Copy");
- if (WaveTableObj->Name == NIL)
- {
- FailurePoint2:
- ReleasePtr((char*)WaveTableObj);
- goto FailurePoint1;
- }
- WaveTableObj->WaveTableFormula = StringToBlockCopy(
- "# data : fixedarray; frames : integer; tables : integer\x0a");
- if (WaveTableObj->WaveTableFormula == NIL)
- {
- FailurePoint3:
- ReleasePtr(WaveTableObj->Name);
- goto FailurePoint2;
- }
- WaveTableObj->WaveTableData = NewWaveTableStorage(NumBits,FramesPerTable);
- if (WaveTableObj->WaveTableData == NIL)
- {
- FailurePoint4:
- ReleasePtr(WaveTableObj->WaveTableFormula);
- goto FailurePoint3;
- }
- for (Scan = 0; Scan < NumTables; Scan += 1)
- {
- if (!WaveTableStorageAppendEntry(WaveTableObj->WaveTableData))
- {
- FailurePoint5:
- DisposeWaveTableStorage(WaveTableObj->WaveTableData);
- goto FailurePoint4;
- }
- }
- for (Scan = 0; Scan < NumTables; Scan += 1)
- {
- long Index;
-
- switch (NumBits)
- {
- default:
- EXECUTE(PRERR(ForceAbort,"NewWaveTableObjectFromData: bad NumBits"));
- break;
- case eSample8bit:
- for (Index = 0; Index < FramesPerTable; Index += 1)
- {
- WaveTableStorageSetFrame(WaveTableObj->WaveTableData,Scan,
- Index,double2largefixed(
- ((double)(((signed char*)RawData)[Scan * FramesPerTable + Index]))
- / MAX8BIT));
- }
- break;
- case eSample16bit:
- for (Index = 0; Index < FramesPerTable; Index += 1)
- {
- WaveTableStorageSetFrame(WaveTableObj->WaveTableData,Scan,
- Index,double2largefixed(
- ((double)(((signed short*)RawData)[Scan * FramesPerTable + Index]))
- / MAX16BIT));
- }
- break;
- }
- }
- return WaveTableObj;
- }
-
-
- /* dispose of a wave table object */
- void DisposeWaveTableObject(WaveTableObjectRec* WaveTableObj)
- {
- CheckPtrExistence(WaveTableObj);
- if (WaveTableObj->WaveTableWindow != NIL)
- {
- DisposeWaveTableWindow(WaveTableObj->WaveTableWindow);
- ERROR(WaveTableObj->WaveTableWindow != NIL,PRERR(ForceAbort,
- "DisposeWaveTableObject: disposed window but it isn't NIL"));
- }
- DisposeWaveTableStorage(WaveTableObj->WaveTableData);
- ReleasePtr(WaveTableObj->Name);
- ReleasePtr(WaveTableObj->WaveTableFormula);
- ReleasePtr((char*)WaveTableObj);
- }
-
-
- /* find out if wave table object has been modified */
- MyBoolean HasWaveTableObjectBeenModified(WaveTableObjectRec* WaveTableObj)
- {
- CheckPtrExistence(WaveTableObj);
- if (WaveTableObj->WaveTableWindow != NIL)
- {
- return WaveTableObj->DataModified
- || HasWaveTableWindowBeenModified(WaveTableObj->WaveTableWindow);
- }
- else
- {
- return WaveTableObj->DataModified;
- }
- }
-
-
- /* get a copy of the wave table's name */
- char* WaveTableObjectGetNameCopy(WaveTableObjectRec* WaveTableObj)
- {
- char* NameTemp;
-
- CheckPtrExistence(WaveTableObj);
- if (WaveTableObj->WaveTableWindow != NIL)
- {
- NameTemp = WaveTableWindowGetNameCopy(WaveTableObj->WaveTableWindow);
- }
- else
- {
- NameTemp = CopyPtr(WaveTableObj->Name);
- }
- if (NameTemp != NIL)
- {
- SetTag(NameTemp,"WaveTableNameCopy");
- }
- return NameTemp;
- }
-
-
- /* set the wave table's name. the object becomes the owner of the Name block, */
- /* so the caller should not release it. */
- void WaveTableObjectNewName(WaveTableObjectRec* WaveTableObj,
- char* Name)
- {
- CheckPtrExistence(WaveTableObj);
- CheckPtrExistence(Name);
- ReleasePtr(WaveTableObj->Name);
- SetTag(Name,"WaveTableName");
- WaveTableObj->Name = Name;
- WaveTableObj->DataModified = True;
- WaveTableListWaveTableNameChanged(WaveTableObj->WaveTableList,WaveTableObj);
- }
-
-
- /* get a copy of the formula applied to the wave table. */
- char* WaveTableObjectGetFormulaCopy(WaveTableObjectRec* WaveTableObj)
- {
- char* TextCopy;
-
- CheckPtrExistence(WaveTableObj);
- if (WaveTableObj->WaveTableWindow != NIL)
- {
- TextCopy = WaveTableWindowGetFormulaCopy(WaveTableObj->WaveTableWindow);
- }
- else
- {
- TextCopy = CopyPtr(WaveTableObj->WaveTableFormula);
- }
- if (TextCopy != NIL)
- {
- SetTag(TextCopy,"WaveTableFormulaCopy");
- }
- return TextCopy;
- }
-
-
- /* install a new formula into the wave table. the object becomes the owner of */
- /* the formula, so the caller should not dispose it. */
- void WaveTableObjectNewFormula(WaveTableObjectRec* WaveTableObj,
- char* Formula)
- {
- CheckPtrExistence(WaveTableObj);
- CheckPtrExistence(Formula);
- ReleasePtr(WaveTableObj->WaveTableFormula);
- SetTag(Formula,"WaveTableFormula");
- WaveTableObj->WaveTableFormula = Formula;
- WaveTableObj->DataModified = True;
- }
-
-
- /* find out whether its 8 or 16 bits. */
- NumBitsType WaveTableObjectGetNumBits(WaveTableObjectRec* WaveTableObj)
- {
- CheckPtrExistence(WaveTableObj);
- if (WaveTableObj->WaveTableWindow != NIL)
- {
- return WaveTableWindowGetNumBits(WaveTableObj->WaveTableWindow);
- }
- else
- {
- return WaveTableStorageNumBits(WaveTableObj->WaveTableData);
- }
- }
-
-
- /* find out how many tables there are in the wave table */
- long WaveTableObjectGetNumTables(WaveTableObjectRec* WaveTableObj)
- {
- CheckPtrExistence(WaveTableObj);
- if (WaveTableObj->WaveTableWindow != NIL)
- {
- return WaveTableWindowGetNumTables(WaveTableObj->WaveTableWindow);
- }
- else
- {
- return WaveTableStorageNumTables(WaveTableObj->WaveTableData);
- }
- }
-
-
- /* find out how many entries there are in a single table */
- long WaveTableObjectEntriesPerTable(WaveTableObjectRec* WaveTableObj)
- {
- CheckPtrExistence(WaveTableObj);
- if (WaveTableObj->WaveTableWindow != NIL)
- {
- return WaveTableWindowGetNumFramesPerTable(WaveTableObj->WaveTableWindow);
- }
- else
- {
- return WaveTableStorageNumFramesPerTable(WaveTableObj->WaveTableData);
- }
- }
-
-
- /* get the raw data for a particular wave table. this returns the actual data, so */
- /* don't dispose it. if any operations are performed on the wave table, this */
- /* pointer may become invalid. the data is in the following format: */
- /* - 8-bit: array of signed bytes */
- /* - 16-bit: array of signed short integers */
- char* WaveTableObjectGetRawSlice(WaveTableObjectRec* WaveTableObj,
- long WaveTableIndex)
- {
- CheckPtrExistence(WaveTableObj);
- ERROR((WaveTableIndex < 0) || (WaveTableIndex
- >= WaveTableObjectGetNumTables(WaveTableObj)),PRERR(ForceAbort,
- "WaveTableObjectGetRawSlice: index out of range"));
- if (WaveTableObj->WaveTableWindow != NIL)
- {
- if (!WaveTableWindowForceWaveTableUpdate(WaveTableObj->WaveTableWindow))
- {
- return NIL;
- }
- }
- return (char*)WaveTableStorageGetTable(WaveTableObj->WaveTableData,WaveTableIndex);
- }
-
-
- /* put new data into the wave table. the object becomes the owner of all data passed in. */
- void WaveTableObjectPutNewData(WaveTableObjectRec* WaveTableObj,
- struct WaveTableStorageRec* NewWaveTable)
- {
- CheckPtrExistence(WaveTableObj);
- CheckPtrExistence(NewWaveTable);
- DisposeWaveTableStorage(WaveTableObj->WaveTableData);
- WaveTableObj->WaveTableData = NewWaveTable;
- WaveTableObj->DataModified = True;
- }
-
-
- /* tell the wave table to open it's editor window */
- MyBoolean WaveTableObjectOpenWindow(WaveTableObjectRec* WaveTableObj)
- {
- CheckPtrExistence(WaveTableObj);
- if (WaveTableObj->WaveTableWindow == NIL)
- {
- WaveTableObj->WaveTableWindow = NewWaveTableWindow(WaveTableObj->MainWindow,
- WaveTableObj,WaveTableObj->CodeCenter,WaveTableObj->WaveTableList,
- WaveTableObj->WaveTableData,WaveTableObj->SavedWindowXLoc,
- WaveTableObj->SavedWindowYLoc,WaveTableObj->SavedWindowWidth,
- WaveTableObj->SavedWindowHeight);
- }
- else
- {
- WaveTableWindowBringToTop(WaveTableObj->WaveTableWindow);
- }
- return (WaveTableObj->WaveTableWindow != NIL);
- }
-
-
- /* this is called by the window when it is closing to notify the object. */
- /* the object should not take any action. */
- void WaveTableObjectClosingWindowNotify(
- WaveTableObjectRec* WaveTableObj, short NewX, short NewY,
- short NewWidth, short NewHeight)
- {
- CheckPtrExistence(WaveTableObj);
- ERROR(WaveTableObj->WaveTableWindow == NIL,PRERR(ForceAbort,
- "WaveTableObjectClosingWindowNotify: window not open"));
- WaveTableObj->WaveTableWindow = NIL;
- WaveTableObj->SavedWindowXLoc = NewX;
- WaveTableObj->SavedWindowYLoc = NewY;
- WaveTableObj->SavedWindowWidth = NewWidth;
- WaveTableObj->SavedWindowHeight = NewHeight;
- }
-
-
- /* obtain a fixedpoint array of data. NIL is returned if there isn't enough memory. */
- largefixedsigned* WaveTableObjectGetFixed(WaveTableObjectRec* WaveTableObj)
- {
- largefixedsigned* Array;
-
- CheckPtrExistence(WaveTableObj);
- if (WaveTableObj->WaveTableWindow == NIL)
- {
- long TableLimit;
- long FrameLimit;
- long TableScan;
-
- TableLimit = WaveTableObjectGetNumTables(WaveTableObj);
- FrameLimit = WaveTableObjectEntriesPerTable(WaveTableObj);
- Array = (largefixedsigned*)AllocPtrCanFail(TableLimit * FrameLimit
- * sizeof(largefixedsigned),"WaveTableFixedArrayCopy");
- if (Array != NIL)
- {
- for (TableScan = 0; TableScan < TableLimit; TableScan += 1)
- {
- long FrameScan;
-
- for (FrameScan = 0; FrameScan < FrameLimit; FrameScan += 1)
- {
- PRNGCHK(Array,&(Array[TableScan * FrameLimit + FrameScan]),
- sizeof(Array[TableScan * FrameLimit + FrameScan]));
- Array[TableScan * FrameLimit + FrameScan]
- = WaveTableStorageGetFrame(WaveTableObj->WaveTableData,
- TableScan,FrameScan);
- }
- }
- }
- }
- else
- {
- Array = WaveTableWindowGetWaveArray(WaveTableObj->WaveTableWindow);
- }
- return Array;
- }
-
-
- /* the document's name has changed, so we need to update the windows */
- void WaveTableObjectGlobalNameChange(WaveTableObjectRec* WaveTableObj,
- char* NewFilename)
- {
- CheckPtrExistence(WaveTableObj);
- if (WaveTableObj->WaveTableWindow != NIL)
- {
- WaveTableWindowGlobalNameChange(WaveTableObj->WaveTableWindow,NewFilename);
- }
- }
-
-
- /* get the test attack duration */
- double WaveTableObjectGetTestAttack(WaveTableObjectRec* WaveTableObj)
- {
- CheckPtrExistence(WaveTableObj);
- if (WaveTableObj->WaveTableWindow != NIL)
- {
- return WaveTableWindowGetAscendingDuration(WaveTableObj->WaveTableWindow);
- }
- else
- {
- return WaveTableObj->TestAttackDuration;
- }
- }
-
-
- /* put a new test attack duration */
- void SetWaveTableObjectTestAttack(WaveTableObjectRec* WaveTableObj,
- double NewTestAttack)
- {
- CheckPtrExistence(WaveTableObj);
- WaveTableObj->TestAttackDuration = NewTestAttack;
- }
-
-
- /* get the test decay duration */
- double WaveTableObjectGetTestDecay(WaveTableObjectRec* WaveTableObj)
- {
- CheckPtrExistence(WaveTableObj);
- if (WaveTableObj->WaveTableWindow != NIL)
- {
- return WaveTableWindowGetDescendingDuration(WaveTableObj->WaveTableWindow);
- }
- else
- {
- return WaveTableObj->TestDecayDuration;
- }
- }
-
-
- /* put a new test decay duration */
- void SetWaveTableObjectTestDecay(WaveTableObjectRec* WaveTableObj,
- double NewTestDecay)
- {
- CheckPtrExistence(WaveTableObj);
- WaveTableObj->TestDecayDuration = NewTestDecay;
- }
-
-
- /* get the test sampling rate */
- long WaveTableObjectGetTestSamplingRate(WaveTableObjectRec* WaveTableObj)
- {
- CheckPtrExistence(WaveTableObj);
- if (WaveTableObj->WaveTableWindow != NIL)
- {
- return WaveTableWindowGetTestSamplingRate(WaveTableObj->WaveTableWindow);
- }
- else
- {
- return WaveTableObj->TestSamplingRate;
- }
- }
-
-
- /* put a new test sampling rate */
- void SetWaveTableObjectTestSamplingRate(WaveTableObjectRec* WaveTableObj,
- long NewTestSamplingRate)
- {
- CheckPtrExistence(WaveTableObj);
- WaveTableObj->TestSamplingRate = NewTestSamplingRate;
- }
-
-
- /* get the test pitch */
- double WaveTableObjectGetTestPitch(WaveTableObjectRec* WaveTableObj)
- {
- CheckPtrExistence(WaveTableObj);
- if (WaveTableObj->WaveTableWindow != NIL)
- {
- return WaveTableWindowGetPitch(WaveTableObj->WaveTableWindow);
- }
- else
- {
- return WaveTableObj->TestFrequency;
- }
- }
-
-
- /* put a new test pitch */
- void SetWaveTableObjectTestPitch(WaveTableObjectRec* WaveTableObj,
- double NewTestPitch)
- {
- CheckPtrExistence(WaveTableObj);
- WaveTableObj->TestFrequency = NewTestPitch;
- }
-
-
- /* Wave Table Object Subblock Format: */
- /* 1-byte format version number */
- /* should be 1 */
- /* 2-byte little endian window X location (signed; origin at upper left corner) */
- /* 2-byte little endian window Y location */
- /* 2-byte little endian window width */
- /* 2-byte little endian window height */
- /* 4-byte little endian wave table name length descriptor */
- /* n-byte name string (line feed = 0x0a) */
- /* 4-byte little endian wave table formula length descriptor */
- /* n-byte formula string (line feed = 0x0a) */
- /* 4-byte little endian large integer encoded test attack duration. */
- /* large integer coded decimal is decimal * 1000000 with a */
- /* range of -1999.999999 to 1999.999999 */
- /* 4-byte little endian large integer encoded test decay duration. */
- /* 4-byte little endian test frequency fractional portion */
- /* unsigned; divide by 2^32 to get the actual fraction */
- /* 4-byte little endian test frequency integer portion */
- /* total test frequency should be between 0.01 and 1e6 */
- /* 4-byte little endian test sampling rate */
- /* should be between 100 and 65535 */
- /* 4-byte little endian number of tables */
- /* 4-byte little endian number of frames per table */
- /* must be an integral power or 2 between 2 and 65536 */
- /* 1-byte number of bits specifier */
- /* must be 8 or 16 */
- /* n-byte sample data for the wave table */
- /* data is stored as follows: each table is stored consecutively starting */
- /* with the table numbered 0. in each table, each sample frame is stored */
- /* consecutively as a signed 2s complement value. 8-bit sample frames */
- /* use 1 byte each. 16-bit sample frames use 2 bytes and are stored little */
- /* endian. */
-
-
- /* load an object from the file */
- FileLoadingErrors WaveTableObjectNewFromFile(WaveTableObjectRec** ObjectOut,
- struct BufferedInputRec* Input, struct CodeCenterRec* CodeCenter,
- struct MainWindowRec* MainWindow,
- struct WaveTableListRec* WaveTableList)
- {
- unsigned char UnsignedChar;
- WaveTableObjectRec* WaveTableObj;
- FileLoadingErrors Error;
- signed short SignedShort;
- unsigned long UnsignedLong;
- signed long SignedLong;
- signed long NumberOfTables;
- signed long NumberOfFrames;
- NumBitsType NumberOfBits;
- long Scan;
-
- CheckPtrExistence(Input);
- CheckPtrExistence(CodeCenter);
- CheckPtrExistence(MainWindow);
- CheckPtrExistence(WaveTableList);
-
- WaveTableObj = (WaveTableObjectRec*)AllocPtrCanFail(sizeof(WaveTableObjectRec),
- "WaveTableObjectRec");
- if (WaveTableObj == NIL)
- {
- Error = eFileLoadOutOfMemory;
- FailurePoint1:
- return Error;
- }
-
- /* 1-byte format version number */
- /* should be 1 */
- if (!ReadBufferedUnsignedChar(Input,&UnsignedChar))
- {
- Error = eFileLoadDiskError;
- FailurePoint2:
- ReleasePtr((char*)WaveTableObj);
- goto FailurePoint1;
- }
- if (UnsignedChar != 1)
- {
- Error = eFileLoadBadFormat;
- FailurePoint3:
- goto FailurePoint2;
- }
-
- /* 2-byte little endian window X location (signed; origin at upper left corner) */
- if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
- {
- Error = eFileLoadDiskError;
- FailurePoint4:
- goto FailurePoint3;
- }
- WaveTableObj->SavedWindowXLoc = SignedShort;
-
- /* 2-byte little endian window Y location */
- if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
- {
- Error = eFileLoadDiskError;
- FailurePoint5:
- goto FailurePoint4;
- }
- WaveTableObj->SavedWindowYLoc = SignedShort;
-
- /* 2-byte little endian window width */
- if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
- {
- Error = eFileLoadDiskError;
- FailurePoint6:
- goto FailurePoint5;
- }
- WaveTableObj->SavedWindowWidth = SignedShort;
-
- /* 2-byte little endian window height */
- if (!ReadBufferedSignedShortLittleEndian(Input,&SignedShort))
- {
- Error = eFileLoadDiskError;
- FailurePoint7:
- goto FailurePoint6;
- }
- WaveTableObj->SavedWindowHeight = SignedShort;
-
- /* 4-byte little endian wave table name length descriptor */
- if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
- {
- Error = eFileLoadDiskError;
- FailurePoint8:
- goto FailurePoint7;
- }
- if (SignedLong < 0)
- {
- Error = eFileLoadBadFormat;
- FailurePoint9:
- goto FailurePoint8;
- }
-
- /* n-byte name string (line feed = 0x0a) */
- WaveTableObj->Name = AllocPtrCanFail(SignedLong,"WaveTableObjectRec: name");
- if (WaveTableObj->Name == NIL)
- {
- Error = eFileLoadOutOfMemory;
- FailurePoint10:
- goto FailurePoint9;
- }
- if (!ReadBufferedInput(Input,SignedLong,WaveTableObj->Name))
- {
- Error = eFileLoadDiskError;
- FailurePoint11:
- ReleasePtr(WaveTableObj->Name);
- goto FailurePoint10;
- }
-
- /* 4-byte little endian wave table formula length descriptor */
- if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
- {
- Error = eFileLoadDiskError;
- FailurePoint12:
- goto FailurePoint11;
- }
- if (SignedLong < 0)
- {
- Error = eFileLoadBadFormat;
- FailurePoint13:
- goto FailurePoint12;
- }
-
- /* n-byte formula string (line feed = 0x0a) */
- WaveTableObj->WaveTableFormula = AllocPtrCanFail(SignedLong,
- "WaveTableObjectRec: formula");
- if (WaveTableObj->WaveTableFormula == NIL)
- {
- Error = eFileLoadOutOfMemory;
- FailurePoint14:
- goto FailurePoint13;
- }
- if (!ReadBufferedInput(Input,SignedLong,WaveTableObj->WaveTableFormula))
- {
- Error = eFileLoadDiskError;
- FailurePoint15:
- ReleasePtr(WaveTableObj->WaveTableFormula);
- goto FailurePoint14;
- }
-
- /* 4-byte little endian large integer encoded test attack duration. */
- /* large integer coded decimal is decimal * 1000000 with a */
- /* range of -1999.999999 to 1999.999999 */
- if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
- {
- Error = eFileLoadDiskError;
- FailurePoint16:
- goto FailurePoint15;
- }
- WaveTableObj->TestAttackDuration = LargeBCD2Double(SignedLong);
- if (WaveTableObj->TestAttackDuration < 0)
- {
- WaveTableObj->TestAttackDuration = 0;
- }
-
- /* 4-byte little endian large integer encoded test decay duration. */
- if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
- {
- Error = eFileLoadDiskError;
- FailurePoint17:
- goto FailurePoint16;
- }
- WaveTableObj->TestDecayDuration = LargeBCD2Double(SignedLong);
- if (WaveTableObj->TestDecayDuration < 0)
- {
- WaveTableObj->TestDecayDuration = 0;
- }
-
- /* 4-byte little endian test frequency fractional portion */
- /* unsigned; divide by 2^32 to get the actual fraction */
- if (!ReadBufferedUnsignedLongLittleEndian(Input,&UnsignedLong))
- {
- Error = eFileLoadDiskError;
- FailurePoint18:
- goto FailurePoint17;
- }
- WaveTableObj->TestFrequency = (double)UnsignedLong / 4294967296.0L;
-
- /* 4-byte little endian test frequency integer portion */
- /* total test frequency should be between 0.01 and 1e6 */
- if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
- {
- Error = eFileLoadDiskError;
- FailurePoint19:
- goto FailurePoint18;
- }
- WaveTableObj->TestFrequency += SignedLong;
- if (WaveTableObj->TestFrequency < MINNATURALFREQ)
- {
- WaveTableObj->TestFrequency = MINNATURALFREQ;
- }
- if (WaveTableObj->TestFrequency > MAXNATURALFREQ)
- {
- WaveTableObj->TestFrequency = MAXNATURALFREQ;
- }
-
- /* 4-byte little endian test sampling rate */
- /* should be between 100 and 65535 */
- if (!ReadBufferedSignedLongLittleEndian(Input,&SignedLong))
- {
- Error = eFileLoadDiskError;
- FailurePoint20:
- goto FailurePoint19;
- }
- if (SignedLong < MINSAMPLINGRATE)
- {
- SignedLong = MINSAMPLINGRATE;
- }
- if (SignedLong > MAXSAMPLINGRATE)
- {
- SignedLong = MAXSAMPLINGRATE;
- }
- WaveTableObj->TestSamplingRate = SignedLong;
-
- /* 4-byte little endian number of tables */
- if (!ReadBufferedSignedLongLittleEndian(Input,&NumberOfTables))
- {
- Error = eFileLoadDiskError;
- FailurePoint21:
- goto FailurePoint20;
- }
- if (NumberOfTables < 0)
- {
- Error = eFileLoadBadFormat;
- FailurePoint22:
- goto FailurePoint21;
- }
-
- /* 4-byte little endian number of frames per table */
- /* must be an integral power or 2 between 2 and 65536 */
- if (!ReadBufferedSignedLongLittleEndian(Input,&NumberOfFrames))
- {
- Error = eFileLoadDiskError;
- FailurePoint23:
- goto FailurePoint22;
- }
- if ((NumberOfFrames != 2) && (NumberOfFrames != 4) && (NumberOfFrames != 8)
- && (NumberOfFrames != 16) && (NumberOfFrames != 32) && (NumberOfFrames != 64)
- && (NumberOfFrames != 128) && (NumberOfFrames != 256) && (NumberOfFrames != 512)
- && (NumberOfFrames != 1024) && (NumberOfFrames != 2048)
- && (NumberOfFrames != 4096) && (NumberOfFrames != 8192)
- && (NumberOfFrames != 16384) && (NumberOfFrames != 32768)
- && (NumberOfFrames != 65536))
- {
- Error = eFileLoadBadFormat;
- FailurePoint24:
- goto FailurePoint23;
- }
-
- /* 1-byte number of bits specifier */
- /* must be 8 or 16 */
- if (!ReadBufferedUnsignedChar(Input,&UnsignedChar))
- {
- Error = eFileLoadDiskError;
- FailurePoint25:
- goto FailurePoint24;
- }
- if (UnsignedChar == 8)
- {
- NumberOfBits = eSample8bit;
- }
- else if (UnsignedChar == 16)
- {
- NumberOfBits = eSample16bit;
- }
- else
- {
- Error = eFileLoadBadFormat;
- FailurePoint26:
- goto FailurePoint25;
- }
-
- /* n-byte sample data for the wave table */
- /* data is stored as follows: each table is stored consecutively starting */
- /* with the table numbered 0. in each table, each sample frame is stored */
- /* consecutively as a signed 2s complement value. 8-bit sample frames */
- /* use 1 byte each. 16-bit sample frames use 2 bytes and are stored little */
- /* endian. */
- WaveTableObj->WaveTableData = NewWaveTableStorage(NumberOfBits,NumberOfFrames);
- if (WaveTableObj->WaveTableData == NIL)
- {
- Error = eFileLoadOutOfMemory;
- FailurePoint27:
- goto FailurePoint26;
- }
- for (Scan = 0; Scan < NumberOfTables; Scan += 1)
- {
- if (!WaveTableStorageAppendEntry(WaveTableObj->WaveTableData))
- {
- Error = eFileLoadOutOfMemory;
- FailurePoint28:
- DisposeWaveTableStorage(WaveTableObj->WaveTableData);
- goto FailurePoint27;
- }
- }
- switch (NumberOfBits)
- {
- default:
- EXECUTE(PRERR(ForceAbort,"WaveTableObjectNewFromFile: bad number of bits"));
- break;
- case eSample8bit:
- for (Scan = 0; Scan < NumberOfTables; Scan += 1)
- {
- long Index;
-
- for (Index = 0; Index < NumberOfFrames; Index += 1)
- {
- signed char SamplePoint;
-
- if (!ReadBufferedSignedChar(Input,&SamplePoint))
- {
- Error = eFileLoadDiskError;
- goto FailurePoint28;
- }
- WaveTableStorageSetFrame(WaveTableObj->WaveTableData,Scan,Index,
- double2largefixed((double)SamplePoint / MAX8BIT));
- }
- }
- break;
- case eSample16bit:
- for (Scan = 0; Scan < NumberOfTables; Scan += 1)
- {
- long Index;
-
- for (Index = 0; Index < NumberOfFrames; Index += 1)
- {
- signed short SamplePoint;
-
- if (!ReadBufferedSignedShortLittleEndian(Input,&SamplePoint))
- {
- Error = eFileLoadDiskError;
- goto FailurePoint28;
- }
- WaveTableStorageSetFrame(WaveTableObj->WaveTableData,Scan,Index,
- double2largefixed((double)SamplePoint / MAX16BIT));
- }
- }
- break;
- }
-
- /* fill in the other fields */
- WaveTableObj->DataModified = False;
- WaveTableObj->WaveTableWindow = NIL;
- WaveTableObj->CodeCenter = CodeCenter;
- WaveTableObj->MainWindow = MainWindow;
- WaveTableObj->WaveTableList = WaveTableList;
-
- *ObjectOut = WaveTableObj;
- return eFileLoadNoError;
- }
-
-
- /* write the object out to the file. */
- FileLoadingErrors WaveTableObjectWriteDataOut(WaveTableObjectRec* WaveTableObj,
- struct BufferedOutputRec* Output)
- {
- char* StringTemp;
- double FrequencyTemp;
- long NumberOfTables;
- long NumberOfFrames;
- NumBitsType NumberOfBits;
- long Scan;
-
- CheckPtrExistence(WaveTableObj);
- CheckPtrExistence(Output);
-
- if (WaveTableObj->WaveTableWindow != NIL)
- {
- if (!WaveTableWindowForceWaveTableUpdate(WaveTableObj->WaveTableWindow))
- {
- return eFileLoadOutOfMemory;
- }
- }
-
- /* 1-byte format version number */
- /* should be 1 */
- if (!WriteBufferedUnsignedChar(Output,1))
- {
- return eFileLoadDiskError;
- }
-
- /* 2-byte little endian window X location (signed; origin at upper left corner) */
- /* note that if the window is open when the file is saved, then the most */
- /* recent coordinates of the window will not be saved */
- if (!WriteBufferedSignedShortLittleEndian(Output,WaveTableObj->SavedWindowXLoc))
- {
- return eFileLoadDiskError;
- }
-
- /* 2-byte little endian window Y location */
- if (!WriteBufferedSignedShortLittleEndian(Output,WaveTableObj->SavedWindowYLoc))
- {
- return eFileLoadDiskError;
- }
-
- /* 2-byte little endian window width */
- if (!WriteBufferedSignedShortLittleEndian(Output,WaveTableObj->SavedWindowWidth))
- {
- return eFileLoadDiskError;
- }
-
- /* 2-byte little endian window height */
- if (!WriteBufferedSignedShortLittleEndian(Output,WaveTableObj->SavedWindowHeight))
- {
- return eFileLoadDiskError;
- }
-
- /* 4-byte little endian wave table name length descriptor */
- StringTemp = WaveTableObjectGetNameCopy(WaveTableObj);
- if (StringTemp == NIL)
- {
- return eFileLoadOutOfMemory;
- }
- if (!WriteBufferedSignedLongLittleEndian(Output,PtrSize(StringTemp)))
- {
- ReleasePtr(StringTemp);
- return eFileLoadDiskError;
- }
-
- /* n-byte name string (line feed = 0x0a) */
- if (!WriteBufferedOutput(Output,PtrSize(StringTemp),StringTemp))
- {
- ReleasePtr(StringTemp);
- return eFileLoadDiskError;
- }
- ReleasePtr(StringTemp);
-
- /* 4-byte little endian wave table formula length descriptor */
- StringTemp = WaveTableObjectGetFormulaCopy(WaveTableObj);
- if (StringTemp == NIL)
- {
- return eFileLoadOutOfMemory;
- }
- if (!WriteBufferedSignedLongLittleEndian(Output,PtrSize(StringTemp)))
- {
- ReleasePtr(StringTemp);
- return eFileLoadDiskError;
- }
-
- /* n-byte formula string (line feed = 0x0a) */
- if (!WriteBufferedOutput(Output,PtrSize(StringTemp),StringTemp))
- {
- ReleasePtr(StringTemp);
- return eFileLoadDiskError;
- }
- ReleasePtr(StringTemp);
-
- /* 4-byte little endian large integer encoded test attack duration. */
- /* large integer coded decimal is decimal * 1000000 with a */
- /* range of -1999.999999 to 1999.999999 */
- if (!WriteBufferedSignedLongLittleEndian(Output,
- Double2LargeBCD(WaveTableObjectGetTestAttack(WaveTableObj))))
- {
- return eFileLoadDiskError;
- }
-
- /* 4-byte little endian large integer encoded test decay duration. */
- if (!WriteBufferedSignedLongLittleEndian(Output,
- Double2LargeBCD(WaveTableObjectGetTestDecay(WaveTableObj))))
- {
- return eFileLoadDiskError;
- }
-
- /* 4-byte little endian test frequency fractional portion */
- /* unsigned; divide by 2^32 to get the actual fraction */
- FrequencyTemp = WaveTableObjectGetTestPitch(WaveTableObj);
- if (!WriteBufferedUnsignedLongLittleEndian(Output,
- (unsigned long)((FrequencyTemp - (long)FrequencyTemp) * 4294967296.0L)))
- {
- return eFileLoadDiskError;
- }
-
- /* 4-byte little endian test frequency integer portion */
- /* total test frequency should be between 0.01 and 1e6 */
- if (!WriteBufferedSignedLongLittleEndian(Output,(long)FrequencyTemp))
- {
- return eFileLoadDiskError;
- }
-
- /* 4-byte little endian test sampling rate */
- /* should be between 100 and 65535 */
- if (!WriteBufferedSignedLongLittleEndian(Output,
- WaveTableObjectGetTestSamplingRate(WaveTableObj)))
- {
- return eFileLoadDiskError;
- }
-
- /* 4-byte little endian number of tables */
- NumberOfTables = WaveTableObjectGetNumTables(WaveTableObj);
- if (!WriteBufferedSignedLongLittleEndian(Output,NumberOfTables))
- {
- return eFileLoadDiskError;
- }
-
- /* 4-byte little endian number of frames per table */
- /* must be an integral power or 2 between 2 and 65536 */
- NumberOfFrames = WaveTableObjectEntriesPerTable(WaveTableObj);
- if (!WriteBufferedSignedLongLittleEndian(Output,NumberOfFrames))
- {
- return eFileLoadDiskError;
- }
-
- /* 1-byte number of bits specifier */
- /* must be 8 or 16 */
- NumberOfBits = WaveTableObjectGetNumBits(WaveTableObj);
- switch (NumberOfBits)
- {
- default:
- EXECUTE(PRERR(ForceAbort,"WaveTableObjectWriteDataOut: bad number of bits"));
- break;
- case eSample8bit:
- if (!WriteBufferedUnsignedChar(Output,8))
- {
- return eFileLoadDiskError;
- }
- break;
- case eSample16bit:
- if (!WriteBufferedUnsignedChar(Output,16))
- {
- return eFileLoadDiskError;
- }
- break;
- }
-
- /* n-byte sample data for the wave table */
- /* data is stored as follows: each table is stored consecutively starting */
- /* with the table numbered 0. in each table, each sample frame is stored */
- /* consecutively as a signed 2s complement value. 8-bit sample frames */
- /* use 1 byte each. 16-bit sample frames use 2 bytes and are stored little */
- /* endian. */
- switch (NumberOfBits)
- {
- default:
- EXECUTE(PRERR(ForceAbort,"WaveTableObjectWriteDataOut: bad number of bits"));
- break;
- case eSample8bit:
- for (Scan = 0; Scan < NumberOfTables; Scan += 1)
- {
- long Index;
- signed char* Slice;
-
- Slice = (signed char*)WaveTableObjectGetRawSlice(WaveTableObj,Scan);
- for (Index = 0; Index < NumberOfFrames; Index += 1)
- {
- PRNGCHK(Slice,&(Slice[Index]),sizeof(Slice[Index]));
- if (!WriteBufferedSignedChar(Output,Slice[Index]))
- {
- return eFileLoadDiskError;
- }
- }
- }
- break;
- case eSample16bit:
- for (Scan = 0; Scan < NumberOfTables; Scan += 1)
- {
- long Index;
- signed short* Slice;
-
- Slice = (signed short*)WaveTableObjectGetRawSlice(WaveTableObj,Scan);
- for (Index = 0; Index < NumberOfFrames; Index += 1)
- {
- PRNGCHK(Slice,&(Slice[Index]),sizeof(Slice[Index]));
- if (!WriteBufferedSignedShortLittleEndian(Output,Slice[Index]))
- {
- return eFileLoadDiskError;
- }
- }
- }
- break;
- }
-
- return eFileLoadNoError;
- }
-
-
- /* mark wave table object as saved */
- void WaveTableObjectMarkAsSaved(WaveTableObjectRec* WaveTableObj)
- {
- CheckPtrExistence(WaveTableObj);
- if (WaveTableObj->WaveTableWindow != NIL)
- {
- WaveTableWindowWritebackModifiedData(WaveTableObj->WaveTableWindow);
- }
- WaveTableObj->DataModified = False;
- }
-